﻿<?php
	set_time_limit(0); //бесконечное время ожидания
	
	defined('_JEXEC') or die('Direct Access to this location is not allowed.');
	
	//класс для работы с прокси
	class Proxy
	{	
		const COUNT = 150; //количество максимальных заходов с одного ip
		private $view = 0; //текущее количество заходов
	
		//необходимо новое соединение при создании
		public function __construct()
		{
			Proxy::NewIdentity();
		}
	
		//новое соединение
		static function NewIdentity($tor_ip='127.0.0.1', $control_port='9051', $auth_code=''){
			$fp = fsockopen($tor_ip, $control_port, $errno, $errstr, 30);
			if (!$fp) return false; //невозможно соединиться с control port
	
			fputs($fp, "AUTHENTICATE $auth_code\r\n");
			$response = fread($fp, 1024);
			list($code, $text) = explode(' ', $response, 2);
			if ($code != '250') return false; //ошибка аутентификации
 
			//запрос на новое соединение
			fputs($fp, "signal NEWNYM\r\n");
			$response = fread($fp, 1024);
			list($code, $text) = explode(' ', $response, 2);
			if ($code != '250') return false; //ошибка сигнала
 
			fclose($fp);
			return true;
		}
		
		//получить страницу
		public function GetPage($url)
		{	
			$this->view += 1;
			if ($this->view > Proxy::COUNT)
			{
				Proxy::NewIdentity();
				$this->view = 1;
			}
			$proxy = "127.0.0.1:9050";
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_PROXY, $proxy);
			curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
			$result = curl_exec($ch);
			curl_close($ch);
			Return $result;
		}
	}
	
	//класс для работы с сайтом
	class Reader
	{	
		private $proxy;
	
		public function __construct()
		{
			$this->proxy = new Proxy();
		}
	
		//массив оригинальных каталогов
		static $cars = array
		(
			"AUDI" 			=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=audi&salerind=223",
			"BMW" 			=> "http://catalogs.choise.ru/bmw/",
			"CHEVROLET" 	=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=chevrolet&salerind=223",
			"CITROEN" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=citroen&salerind=223",
			"DAEWOO" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=daewoo&salerind=223",
			"FIAT" 			=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=fiat&salerind=223",
			"FORD" 			=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=ford&salerind=223",
			"HONDA" 		=> "http://catalogs.choise.ru/honda/",
			"HYUNDAI" 		=> "http://catalogs.choise.ru/hyundai/",
			"KIA" 			=> "http://catalogs.choise.ru/kia/",
			"LEXUS" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=lexus&salerind=223",
			"MAZDA" 		=> "http://catalogs.choise.ru/mazda/",
			"MERCEDES BENZ" => "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=mercl&salerind=223",
			"MITSUBISHI" 	=> "http://catalogs.choise.ru/mitsubishi/",
			"NISSAN" 		=> "http://catalogs.choise.ru/nissan/",
			"PEUGEOT" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=pego&salerind=223",
			"PORSCHE" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=porsche&salerind=223",
			"RENAULT" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=renault&salerind=223",
			"SAAB" 			=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=saab&salerind=223",
			"SSANG YONG" 	=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=ssangyong&salerind=223",
			"SUBARU" 		=> "http://catalogs.choise.ru/subaru/",
			"SUZUKI" 		=> "http://catalogs.choise.ru/suzuki/",
			"TOYOTA" 		=> "http://catalogs.choise.ru/toyota/",
			"VOLKSWAGEN" 	=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=vw&salerind=223",
			"VOLVO" 		=> "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&mark=volvol&salerind=223"
		);
		
		static $carsNamings = array
		(
			"AUDI" 			=> "audi",
			"BMW" 			=> "bmw",
			"CHEVROLET" 	=> "chevrolet",
			"CITROEN" 		=> "citroen",
			"DAEWOO" 		=> "daewoo",
			"FIAT" 			=> "fiat",
			"FORD" 			=> "ford",
			"HONDA" 		=> "honda",
			"HYUNDAI" 		=> "hyundai",
			"KIA" 			=> "kia",
			"LEXUS" 		=> "lexus",
			"MAZDA" 		=> "mazda",
			"MERCEDES BENZ" => "mercl",
			"MITSUBISHI" 	=> "mitsubishi",
			"NISSAN" 		=> "nissan",
			"PEUGEOT" 		=> "pego",
			"PORSCHE" 		=> "porsche",
			"RENAULT" 		=> "renault",
			"SAAB" 			=> "saab",
			"SSANG YONG" 	=> "ssangyong",
			"SUBARU" 		=> "subaru",
			"SUZUKI" 		=> "suzuki",
			"TOYOTA" 		=> "toyota",
			"VOLKSWAGEN" 	=> "vw",
			"VOLVO" 		=> "volvol"
		);
		
		public function UpdateModels()
		{	
			WorkWithDB::ClearModels();
		
			echo 'Дата начала '.date("H:i:s").'<br>';
			foreach(static::$cars as $brend=>$original) //$brend - марка автомобиля, $original - ссылка на каталог оригинальных запчастей
			{
				$series = $this->Parser($original, 'serie'); //$serie - серия
				foreach($series as $serie)
				{
					echo $serie.'<br>';
					$mades = $this->Parser($original.'&serie='.$serie, 'made'); //$made - год выпуска
					foreach($mades as $made)
					{
						//echo '->'.$made.'<br>';
						$kuzovs = $this->Parser($original.'&serie='.$serie.'&made='.$made, 'kuzov'); //$kuzov - тип кузова
						foreach($kuzovs as $kuzov)
						{
							//echo '->->'.$kuzov.'<br>';
							$fuels  = $this->Parser($original.'&serie='.$serie.'&made='.$made.'&kuzov='.$kuzov, 'fuel'); //$fuel - тип двигателя
							foreach($fuels as $fuel)
							{
								//echo '->->->'.$fuel.'<br>';
								$motors  = $this->Parser($original.'&serie='.$serie.'&made='.$made.'&kuzov='.$kuzov.'&fuel='.$fuel, 'motor'); //motor - тип двигателя
								foreach($motors as $motor)
								{	
									//echo '->->->->'.$motor.'<br>';
									$tcodaxps  = $this->Parser($original.'&serie='.$serie.'&made='.$made.'&kuzov='.$kuzov.'&fuel='.$fuel.'&motor='.$motor, 'tcodaxp'); //$tcodaxp - модель
									foreach($tcodaxps as $tcodaxp)
									{
										//echo '->->->->->'.$original.'&serie='.$serie.'&made='.$made.'&kuzov='.$kuzov.'&fuel='.$fuel.'&motor='.$motor.'&tcodaxp='.$tcodaxp.'<br>';
										WorkWithDB::AddModel($brend, $serie, $made, $kuzov, $fuel, $motor, $tcodaxp);
									}
								}
							}
						}
					}
				}
			}
			echo 'Дата конца '.date("H:i:s").'<br>';
		}
		
		public function UpdatePrice()
		{
			WorkWithDB::ClearPrices();
			
			echo 'Дата начала '.date("H:i:s").'<br>';
			foreach(static::$carsNamings as $brend=>$naming) //$brend - марка автомобиля, $original - ссылка на каталог оригинальных запчастей
			{
				$cods = WorkWithDB::GetCods($brend);
				foreach($cods as $cod)
				{
					//echo $cod.'<br>';
					
					//echo "http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&salerind=223&mark=".$naming."&codaxp=".$cod;
					//return;
					$grnums = $this->ParserGrnum("http://app.autoxp.ru/pscomplex/catalog.aspx?clstep=catalog&salerind=223&mark=".$naming."&codaxp=".$cod);
					foreach($grnums as $grnum_value=>$grnum_href)
					{
						//echo $grnum_value.' '.$grnum_href.'<br>';
						
						$pdgrnums = $this->ParserPdgrnum("http://app.autoxp.ru".$grnum_href);
						
						foreach($pdgrnums as $pdgrnum)
						{
							$elems = $this->ParserElemPdgrnum("http://app.autoxp.ru".$pdgrnum);	
							foreach($elems as $elem_name=>$elem_href)
							{
								//echo $elem_name.' '.$elem_href.'<br>';
								$prices = $this->ParesePrice($brend, $elem_href);
								foreach($prices as $price)
								{
									WorkWithDB::AddPrice($cod, 0, $grnum_value, 0, $elem_name, 0, $price[0], $price[1], $price[2], $price[3], $price[4], $price[5], $price[6], $price[7], $price[8], $price[9]);
									echo $price[1].' '.$price[2].'<br>';
									//AddPrice($tcodaxp, $grnum, $grnum_name, $pdgrnum, $elem_name, $numpart, $p_articul, $p_detail_name, $p_price, $p_weight, $p_delivery, $p_presence, $p_party, $p_period, $p_date, $p_direction)
								}
								
								return;
							}
						}
					}
				}
			}
			echo 'Дата конца '.date("H:i:s").'<br>';
		}
		
		
		
		private function ParesePrice($brend, $html)
		{
			$result = array();
		
			//определение для конкретной модели
			$dom = new domDocument;

			$html = $this->proxy->GetPage($html);
			@$dom->loadHTML($html);
			
			$next_html = '';
			
			//если страница перемещена
			if (count($h2 = $dom->getElementsByTagName('h2')) == 1)
			{
				$html = $h2->item(0)->getElementsByTagName('a')->item(0)->getAttribute('href');
				$html = $this->proxy->GetPage($html);
				@$dom->loadHTML($html);
			}
			
			//если страница с выбором альтернативных производителей
			if (strpos($html, iconv("UTF-8", "Windows-1251", "История поиска деталей")) === false)
			{
				$tables = $dom->getElementsByTagName('table');
				foreach($tables as $table)
				{
					$trs = $table->getElementsByTagName('tr');
					echo cunt($trs).'<br>';
					foreach($trs as $tr)
					{		
						$tds = $tr->getElementsByTagName('td');
						if ($tds->length > 0)
						{
								if (strpos($tds->item(0)->nodeValue, $brend) !== false)
								//echo $name.'<br>';
								//echo $tds->item(2)->getElementsByTagName('a')->item(0)->getAttribute('href');
								$next_html = "www.choise.ru".$tds->item(2)->getElementsByTagName('a')->item(0)->getAttribute('href');
						}		
					}
				}
			}

			if ($next_html <> '')
			{
				$html = $this->proxy->GetPage($next_html);
				@$dom->loadHTML($html);
			}
			
			//получаем цены всех деталей
			$tables = $dom->getElementsByTagName('table');
			foreach($tables as $table)
			{
				if ($table->hasAttribute('class') & ($table->getAttribute('class') == 'web_ar_datagrid'))
				{
					$trs = $table->getElementsByTagName('tr');
					foreach($trs as $tr)
					{
						if ($tr->hasAttribute('class'))
						{
							$tds = $tr->getElementsByTagName('td');
							
							$articul = $tds->item(1)->nodeValue; //артикул
							$detail_name = trim($tds->item(2)->nodeValue); //название детали
							$price = trim($tds->item(4)->nodeValue); //цена
							$weight = $tds->item(5)->nodeValue; //вес (кг)
							$delivery = $tds->item(6)->nodeValue; //дост. (р./кг)
							$presence = $tds->item(7)->nodeValue; //наличие
							$party = $tds->item(8)->nodeValue; //партия
							$period = $tds->item(9)->nodeValue; //срок (раб.дн.)
							$date = $tds->item(10)->nodeValue; //дата
							$direction = $tds->item(13)->nodeValue; //направление
							
							$result[] = array ($articul, $detail_name, $price, $weight, $delivery, $presence, $party, $period, $date, $direction);
							/*
							echo $articul.'<br>';
							echo $detail_name.'<br>';
							echo $price.'<br>';
							echo $weight.'<br>';
							echo $delivery.'<br>';
							echo $presence.'<br>';
							echo $party.'<br>';
							echo $period.'<br>';
							echo $date.'<br>';
							echo $direction.'<br>';
							
							echo '====='.'<br>';
							*/
						}
					}
				}
			}
			return $result;
		}
		
		//Парсинг составных элементов подгруппы (шланг воздушный прав., шланг воздушный лев. и т.д.)
		private function ParserElemPdgrnum($html)
		{
			$result = array();
		
			$dom = new domDocument;
			$html = $this->proxy->GetPage($html);
			@$dom->loadHTML($html);
			$trs = $dom->getElementsByTagName('tr');
			foreach($trs as $tr)
			{
				if ($tr->hasAttribute('onclick'))
				{
					$tds = $tr->getElementsByTagName('td');
		
					$name = $tds->item(1)->nodeValue;
					$href = $tds->item(2)->getElementsByTagName('a')->item(0)->getAttribute('href');
					
					//echo $name.' '.$href.'<br>';
					$result[$name] = $href;
				}
			}
			return $result;
		}
		
		//Парсинг подгруппы группы деталей
		private function ParserPdgrnum($html)
		{
			$result = array();

			$dom = new domDocument;
			$html = $this->proxy->GetPage($html);
			@$dom->loadHTML($html);
			$imgs = $dom->getElementsByTagName('img');
			foreach($imgs as $img)
			{
				if ($img->hasAttribute('class') & ($img->getAttribute('class') == 'IMG1'))
				{
					//echo $img->getAttribute('class').'<br>';
					//echo $img->parentNode->getAttribute('href').'<br>';
					$result[] = $img->parentNode->getAttribute('href');
				}
			}
			return $result;
		}
		
		//Парсинг группы деталей (панель приборов, ходовая часть, кузов и т.д.)
		private function ParserGrnum($html)
		{
			$result = array();
		
			$dom = new domDocument;
			$html = $this->proxy->GetPage($html);
			@$dom->loadHTML($html);
			$as = $dom->getElementsByTagName('a');
			foreach($as as $a)
			{
				$ds = $a->getElementsByTagName('b');
				if ($ds->length == 0)
				{
					$value = $a->nodeValue;
					$href =  $a->getAttribute('href');
					if (trim($value) != '')
					{
						//echo $value.' '.$href.'<br>';
						$result[$value] = $href;
					}
				}
			}
			return $result;
		}
		
		//Парсинг моделей
		private function Parser($_html, $_name)
		{
			$result = array();

			$dom = new domDocument;
			$_html = str_replace(' ', '%20', $_html);

			$html = $this->proxy->GetPage($_html);
			//echo $html;
			/*
			$html = file_get_contents($_html);
			if (strpos($html, 'Доступ временно прерван') !== false)
			{
				$time = 60*(60-date("i"))-date("s"); //число секунд до следующего часа
				sleep($time); //ждем начала следующего часа
				$html = file_get_contents($_html);
			}
			*/
			@$dom->loadHTML($html);
			
			$selects = $dom->getElementsByTagName('select');
			foreach($selects as $select)
			{
				$name =  $select->getAttribute('name');
				if ($name == $_name)
				{
					$options = $select->getElementsByTagName('option');
					foreach($options as $option)
					{
						$value = $option->getAttribute('value');
						if ($value <> 'false')
						{
							$result[] = $value;
						}
					}
				}
			}
			
			return $result;
		}
	}
	
	//класс для работы с базой данных
	class DB
	{
		const host = "localhost";
		const user = "avt";
		const pass = "avt";
		const db = "avt";

		//выполнить запрос
		static function Query($query)
		{
			//открытие соединения
			$link = mysql_connect(DB::host,DB::user,DB::pass) or die('Не могу соедениться с MySQL: '.mysql_error());
			mysql_select_db(DB::db,$link) or die('Не могу выбрать базу: '.DB::db.'. Ошибка: '.mysql_error($link));

			mysql_query($query) or die('Ошибка выполнения запроса: '.mysql_error());
			
			//закрытие соединения
			mysql_close();
		}
		
		static function GetCods($query)
		{
			//открытие соединения
			$link = mysql_connect(DB::host,DB::user,DB::pass) or die('Не могу соедениться с MySQL: '.mysql_error());
			mysql_select_db(DB::db,$link) or die('Не могу выбрать базу: '.DB::db.'. Ошибка: '.mysql_error($link));
			
			$cods = array();
			
			$result = mysql_query($query) or die('Query failed: ' . mysql_error());
			
			while ($line = mysql_fetch_array($result, MYSQL_NUM))
			{
				$cods[] = $line[0];
			}
			
			//закрытие соединения
			mysql_close();
			
			Return $cods;
		}
	}
	
	class WorkWithDB
	{
		static function AddModel($brend, $serie, $made, $kuzov, $fuel, $motor, $tcodaxp)
		{
			DB::Query(iconv("UTF-8", "Windows-1251", "insert into avt_models (brend, serie, made, kuzov, fuel, motor, tcodaxp) 
				values ('$brend', '$serie', $made, '$kuzov', '$fuel', '$motor', $tcodaxp)"));
		}
		
		static function ClearModels()
		{
			DB::Query("delete from avt_models");
		}
		
		static function GetCods($brnd)
		{
			$query = "select distinct tcodaxp from avt_models where brend = '".$brnd."'";
			Return DB::GetCods($query);
		}
		
		static function ClearPrices()
		{
			DB::Query("delete from avt_prices");
		}
		
		static function AddPrice($tcodaxp, $grnum, $grnum_name, $pdgrnum, $elem_name, $numpart, $p_articul, $p_detail_name, $p_price, $p_weight, $p_delivery, $p_presence, $p_party, $p_period, $p_date, $p_direction)
		{
			DB::Query(iconv("UTF-8", "Windows-1251", "insert into avt_prices (tcodaxp, grnum, grnum_name, pdgrnum, elem_name, numpart, p_articul, p_detail_name, p_price, p_weight, p_delivery, p_presence, p_party, p_period, p_date, p_direction) 
				values ($tcodaxp, $grnum, '$grnum_name', $pdgrnum, '$elem_name', $numpart, $p_articul, '$p_detail_name', '$p_price', '$p_weight', '$p_delivery', '$p_presence', '$p_party', '$p_period', '$p_date', '$p_direction')"));
		}
	}
	
	$choise = new Reader();
	$choise->UpdatePrice();

?>